﻿using Microsoft.CodeAnalysis;
using Sys.Workflow.Bpmn.Models;
using Sys.Workflow.Engine.Impl.Persistence.Entity;
using Sys.Workflow.Engine.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sys.Workflow.Engine.dynamic
{
    /* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

    /**
     * @author Dennis
     */
    //Auxiliary class to kick off a changeActivityState / processMigration and store its state
    public class ProcessInstanceChangeState
    {

        protected string processInstanceId;
        protected IProcessDefinition processDefinitionToMigrateTo;
        protected Dictionary<string, object> processVariables = new Dictionary<string, object>();
        protected Dictionary<string, Dictionary<string, object>> localVariables = new Dictionary<string, Dictionary<string, object>>();
        protected Dictionary<string, List<IExecutionEntity>> processInstanceActiveEmbeddedExecutions;
        protected List<MoveExecutionEntityContainer> moveExecutionEntityContainers;
        protected List<EnableActivityContainer> enableActivityContainers;
        protected Dictionary<string, IExecutionEntity> createdEmbeddedSubProcess = new Dictionary<string, IExecutionEntity>();
        protected Dictionary<string, IExecutionEntity> createdMultiInstanceRootExecution = new Dictionary<string, IExecutionEntity>();
        protected Dictionary<StartEvent, IExecutionEntity> pendingEventSubProcessesStartEvents = new Dictionary<StartEvent, IExecutionEntity>();

        public ProcessInstanceChangeState()
        {
        }

        public string GetProcessInstanceId()
        {
            return processInstanceId;
        }

        public ProcessInstanceChangeState SetProcessInstanceId(string processInstanceId)
        {
            this.processInstanceId = processInstanceId;
            return this;
        }

        public IProcessDefinition GetProcessDefinitionToMigrateTo()
        {
            return processDefinitionToMigrateTo;
        }

        public ProcessInstanceChangeState SetProcessDefinitionToMigrateTo(IProcessDefinition processDefinitionToMigrateTo)
        {
            this.processDefinitionToMigrateTo = processDefinitionToMigrateTo;
            return this;
        }

        public bool IsMigrateToProcessDefinition()
        {
            return processDefinitionToMigrateTo != null;
        }

        public Dictionary<string, object> GetProcessInstanceVariables()
        {
            return processVariables;
        }

        public ProcessInstanceChangeState SetProcessInstanceVariables(Dictionary<string, object> processVariables)
        {
            this.processVariables = processVariables;
            return this;
        }

        public Dictionary<string, Dictionary<string, object>> GetLocalVariables()
        {
            return localVariables;
        }

        public ProcessInstanceChangeState SetLocalVariables(Dictionary<string, Dictionary<string, object>> localVariables)
        {
            this.localVariables = localVariables;
            return this;
        }

        public List<EnableActivityContainer> GetEnableActivityContainers()
        {
            return enableActivityContainers;
        }

        public ProcessInstanceChangeState SetEnableActivityContainers(List<EnableActivityContainer> enableActivityContainers)
        {
            this.enableActivityContainers = enableActivityContainers;
            return this;
        }

        public List<MoveExecutionEntityContainer> GetMoveExecutionEntityContainers()
        {
            return moveExecutionEntityContainers;
        }

        public ProcessInstanceChangeState SetMoveExecutionEntityContainers(List<MoveExecutionEntityContainer> moveExecutionEntityContainers)
        {
            this.moveExecutionEntityContainers = moveExecutionEntityContainers;
            return this;
        }

        public Dictionary<string, IExecutionEntity> GetCreatedEmbeddedSubProcesses()
        {
            return createdEmbeddedSubProcess;
        }

        public IExecutionEntity GetCreatedEmbeddedSubProcessByKey(string key)
        {
            return createdEmbeddedSubProcess[key];
        }

        public void AddCreatedEmbeddedSubProcess(string key, IExecutionEntity executionEntity)
        {
            this.createdEmbeddedSubProcess.Add(key, executionEntity);
        }

        public Dictionary<string, IExecutionEntity> GetCreatedMultiInstanceRootExecution()
        {
            return createdMultiInstanceRootExecution;
        }

        public void SetCreatedMultiInstanceRootExecution(Dictionary<string, IExecutionEntity> createdMultiInstanceRootExecution)
        {
            this.createdMultiInstanceRootExecution = createdMultiInstanceRootExecution;
        }

        public void AddCreatedMultiInstanceRootExecution(string key, IExecutionEntity executionEntity)
        {
            this.createdMultiInstanceRootExecution.Add(key, executionEntity);
        }

        public Dictionary<string, List<IExecutionEntity>> GetProcessInstanceActiveEmbeddedExecutions()
        {
            return processInstanceActiveEmbeddedExecutions;
        }

        public ProcessInstanceChangeState SetProcessInstanceActiveEmbeddedExecutions(Dictionary<string, List<IExecutionEntity>> processInstanceActiveEmbeddedExecutions)
        {
            this.processInstanceActiveEmbeddedExecutions = processInstanceActiveEmbeddedExecutions;
            return this;
        }

        public Dictionary<StartEvent, IExecutionEntity> GetPendingEventSubProcessesStartEvents()
        {
            return pendingEventSubProcessesStartEvents;
        }

        public void AddPendingEventSubProcessStartEvent(StartEvent startEvent, IExecutionEntity eventSubProcessParent)
        {
            this.pendingEventSubProcessesStartEvents.Add(startEvent, eventSubProcessParent);
        }

    }
}
